package com.loongtech.bi.manager.player;

import com.loongtech.bi.manager.system.BiPlatformManager;
import com.loongtech.bi.support.chart.ChartData1;
import com.loongtech.bi.support.chart.ChartFlow;
import com.loongtech.bi.support.chart.ChartSelect;
import com.loongtech.core.jpa.manager.ManagerQueryCacheBase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 玩家分析-新增分析manager
 *
 * @author marin
 * @date 2015-09-15
 */
@Service
public class NewAddPlayerManager extends ManagerQueryCacheBase<Object> {
    private static final long serialVersionUID = 1L;

    @Autowired
    private NewUserManager newUserManager;
    @Autowired
    private SevenLoginPercentManager sevenLoginPercentManager;
    @Autowired
    UserTwoStepLoginPercentManager userTwoStepLoginPercentManager;
    @Autowired
    ActiveDeviceManager activeDeviceManager;
    @Autowired
    NewDeviceManager newDeviceManager;

    //用户指标
    public List<NewAddUserData> getNewAddUserData(Date dateStart, Date dateEnd, String queryPlatform, String queryChannel, String queryServer) {
        List<NewAddUserData> result = new ArrayList<NewAddUserData>();
        //map
        Map<String, NewAddUserData> map = new HashMap<String, NewAddUserData>();

        //新增账号
        List<Object[]> newUserList = newUserManager.getNewUserByAllKind(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
        for (Object[] o : newUserList) {
            NewAddUserData NewAddUserData = new NewAddUserData();
            NewAddUserData.setDay(o[0].toString());
            NewAddUserData.setNewUser(Integer.parseInt(o[1].toString()));
            //map 存入
            map.put(o[0].toString(), NewAddUserData);
        }

        //7日登录占比
        List<Object[]> list = sevenLoginPercentManager.getSevenLoginPercentByAllKind(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
        for (Object[] o : list) {
            NewAddUserData NewAddUserData = map.get(o[0].toString());

            if (NewAddUserData != null) {
                NewAddUserData.setAvailabilityUser(o[1] == null ? 0 : Integer.parseInt(o[1].toString()));
                NewAddUserData.setRetainedUser(o[2] == null ? 0 : Integer.parseInt(o[2].toString()));
                NewAddUserData.setLoginPercent(o[3] == null ? 0 : Float.parseFloat(o[3].toString()));
                //map 存入
                map.put(o[0].toString(), NewAddUserData);
            }
        }

        // 二阶登录比
        List<Object[]> list2 = userTwoStepLoginPercentManager.getUserTwoStepLoginPercentByAllKind(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
        for (Object[] o : list2) {
            NewAddUserData NewAddUserData = map.get(o[0].toString());

            if (NewAddUserData != null) {
                NewAddUserData.setThe3LoginUserNumOfFirstWeek(o[1] == null ? 0 : Integer.parseInt(o[1].toString()));
                NewAddUserData.setThe1LoginUserNumOfSecondWeek(o[2] == null ? 0 : Integer.parseInt(o[2].toString()));
                NewAddUserData.setLoginPercent2(o[3] == null ? 0 : Float.parseFloat(o[3].toString()));
                //map 存入
                map.put(o[0].toString(), NewAddUserData);
            }
        }

        //遍历存入结果
        for (Object[] o : newUserList) {
            NewAddUserData NewAddUserData = map.get(o[0].toString());

            if (NewAddUserData != null) {
                result.add(NewAddUserData);
            }
        }

        return result;
    }

    //用户指标
    public class NewAddUserData {
        private String platformId;
        private String channelId;
        private String serverId;
        @ChartFlow(name = "日期")
        private String day; // 日期

        @ChartSelect(name = "新增用户数", key = 1)
        @ChartData1(name = "新增用户数", key = 1)
        private int newUser; //
        @ChartData1(name = "登录比有效用户数", key = 1)
        private int availabilityUser; //
        @ChartData1(name = "登录比留存用户数", key = 1)
        private int retainedUser; //
        private float loginPercent; //
        private int the3LoginUserNumOfFirstWeek;  // 首周登录三天用户数
        private int the1LoginUserNumOfSecondWeek;  // 次周登录过的用户数
        private float loginPercent2; // 二阶登录比

        public String getPlatformId() {
            return platformId;
        }

        public void setPlatformId(String platformId) {
            this.platformId = platformId;
        }

        public String getChannelId() {
            return channelId;
        }

        public void setChannelId(String channelId) {
            this.channelId = channelId;
        }

        public String getServerId() {
            return serverId;
        }

        public void setServerId(String serverId) {
            this.serverId = serverId;
        }

        public String getDay() {
            return day;
        }

        public void setDay(String day) {
            this.day = day;
        }

        public int getNewUser() {
            return newUser;
        }

        public void setNewUser(int newUser) {
            this.newUser = newUser;
        }

        public int getAvailabilityUser() {
            return availabilityUser;
        }

        public void setAvailabilityUser(int availabilityUser) {
            this.availabilityUser = availabilityUser;
        }

        public int getRetainedUser() {
            return retainedUser;
        }

        public void setRetainedUser(int retainedUser) {
            this.retainedUser = retainedUser;
        }

        public float getLoginPercent() {
            return loginPercent;
        }

        public void setLoginPercent(float loginPercent) {
            this.loginPercent = loginPercent;
        }

        public int getThe3LoginUserNumOfFirstWeek() {
            return the3LoginUserNumOfFirstWeek;
        }

        public void setThe3LoginUserNumOfFirstWeek(int the3LoginUserNumOfFirstWeek) {
            this.the3LoginUserNumOfFirstWeek = the3LoginUserNumOfFirstWeek;
        }

        public int getThe1LoginUserNumOfSecondWeek() {
            return the1LoginUserNumOfSecondWeek;
        }

        public void setThe1LoginUserNumOfSecondWeek(int the1LoginUserNumOfSecondWeek) {
            this.the1LoginUserNumOfSecondWeek = the1LoginUserNumOfSecondWeek;
        }

        public float getLoginPercent2() {
            return loginPercent2;
        }

        public void setLoginPercent2(float loginPercent2) {
            this.loginPercent2 = loginPercent2;
        }
    }

    public List<NewPlayerData> getNewPlayerDatas(Date dateStart, Date dateEnd, String queryPlatform, String queryChannel, String queryServer) {
        List<NewPlayerData> result = new ArrayList<>();
        Map<String, NewPlayerData> map = new HashMap<>();

        // 激活设备
        List<Object[]> activeDeviceList = activeDeviceManager.getActiveDeviceByAllKind(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
        if (activeDeviceList != null && activeDeviceList.size() > 0 && activeDeviceList.get(0)[0] != null) {
            for(Object[] o : activeDeviceList) {
                String day = o[0].toString();
                NewPlayerData tmp = map.get(day);
                if (tmp == null) {
                    tmp = new NewPlayerData();
                    tmp.setDay(day);
                    map.put(day, tmp);
                }
                tmp.setActiveDevice(Integer.parseInt(o[1].toString()));
            }
        }

        // 新增设备
        List<Object[]> newDeviceList = newDeviceManager.getNewDeviceByAllKind(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
        if (newDeviceList != null && newDeviceList.size() > 0 && newDeviceList.get(0)[0] != null) {
            for(Object[] o : newDeviceList) {
                String day = o[0].toString();
                NewPlayerData tmp = map.get(day);
                if (tmp == null) {
                    tmp = new NewPlayerData();
                    tmp.setDay(day);
                    map.put(day, tmp);
                }
                tmp.setNewDevice(Integer.parseInt(o[1].toString()));
                tmp.setActive2NewRadio(tmp.getActiveDevice() == 0 ? 0 : (float)(tmp.getNewDevice() * 1.0 / tmp.getActiveDevice()));
            }
        }

        //新增账号
        List<Object[]> newUserList = newUserManager.getNewUserByAllKind(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
        if (newUserList != null && newUserList.size() > 0 && newUserList.get(0)[0] != null) {
            for (Object[] o : newUserList) {
                String day = o[0].toString();
                NewPlayerData tmp = map.get(day);
                if (tmp == null) {
                    tmp = new NewPlayerData();
                    tmp.setDay(day);
                    map.put(day, tmp);
                }
                tmp.setNewUser(Integer.parseInt(o[1].toString()));
            }
        }

        if (map.size() > 0) {
            result.addAll(new ArrayList<>(map.values()));
            Collections.sort(result, new NewPlayerData().comparatorDate);
        }

        return result;
    }


    public List<NewPlayerByChannelData> getNewPlayerByChannelDatas(Date dateStart, Date dateEnd, String queryPlatform, String queryChannel, String queryServer) {
        List<NewPlayerByChannelData> result = new ArrayList<>();
        Map<String, Map<String, NewPlayerByChannelData>> map = new HashMap<>();
        Set<String> channels = new HashSet<>();

        List<Object[]> list = newUserManager.getNewUserGroupByChannelDate(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
        if (list != null && list.size() > 0 && list.get(0)[0] != null) {
            for(Object[] o : list) {
                String day = o[0].toString();
                String channelId = o[1].toString();

                channels.add(channelId);

                Map<String, NewPlayerByChannelData> tmpMap = map.get(day);
                if (tmpMap == null) {
                    tmpMap = new HashMap<>();
                    map.put(day, tmpMap);
                }

                NewPlayerByChannelData tmp = tmpMap.get(channelId);
                if (tmp == null) {
                    tmp = new NewPlayerByChannelData();
                    tmp.setChannelId(channelId);
                    tmp.setDay(day);
                    tmpMap.put(channelId, tmp);
                }
                tmp.setNewUser(Integer.parseInt(o[2].toString()));
            }
        }

        if (map.size() > 0) {
            for (Map.Entry<String, Map<String, NewPlayerByChannelData>> entry : map.entrySet()) {
                Map<String, NewPlayerByChannelData> v = entry.getValue();
                for (String c : channels) {
                    NewPlayerByChannelData r = v.get(c);
                    if (r == null) {
                        r = new NewPlayerByChannelData();
                        r.setDay(entry.getKey());
                        r.setChannelId(c);
                    }
                    result.add(r);
                }
            }

            Collections.sort(result, new NewPlayerByChannelData().comparatorDateAndChannel);
        }

        return result;
    }

    public class NewPlayerData {
        @ChartFlow(name = "日期")
        private String day;

        @ChartSelect(name = "新增帐号数", key = 1)
        @ChartData1(name = "新增帐号数", key = 1)
        private int newUser;
        @ChartSelect(name = "激活设备数", key = 2)
        @ChartData1(name = "激活设备数", key = 2)
        private int activeDevice;
        private int newDevice;
        @ChartSelect(name = "激活-新增转化率", key = 3)
        @ChartData1(name = "激活-新增转化率", key = 3)
        private float active2NewRadio;

        public final Comparator<NewPlayerData> comparatorDate = new Comparator<NewPlayerData>() {
            @Override
            public int compare(NewPlayerData s1, NewPlayerData s2) {
                return s2.getDay().compareTo(s1.getDay());
            }
        };

        public String getDay() {
            return day;
        }

        public void setDay(String day) {
            this.day = day;
        }

        public int getNewUser() {
            return newUser;
        }

        public void setNewUser(int newUser) {
            this.newUser = newUser;
        }

        public int getActiveDevice() {
            return activeDevice;
        }

        public void setActiveDevice(int activeDevice) {
            this.activeDevice = activeDevice;
        }

        public int getNewDevice() {
            return newDevice;
        }

        public void setNewDevice(int newDevice) {
            this.newDevice = newDevice;
        }

        public float getActive2NewRadio() {
            return active2NewRadio;
        }

        public void setActive2NewRadio(float active2NewRadio) {
            this.active2NewRadio = active2NewRadio;
        }
    }

    public class NewPlayerByChannelData {
        private String channelId;
        private String channelName;

        @ChartFlow(name = "日期")
        private String day;
        @ChartSelect(name = "新增帐号数", key = 1)
        @ChartData1(name = "新增帐号数", key = 1, multiByFiled = "channelName")
        private int newUser;

        public final Comparator<NewPlayerByChannelData> comparatorDateAndChannel = new Comparator<NewPlayerByChannelData>() {
            @Override
            public int compare(NewPlayerByChannelData s1, NewPlayerByChannelData s2) {
                int r = s2.getDay().compareTo(s1.getDay());
                return r == 0 ? s2.getChannelId().compareTo(s1.getChannelId()): r;
            }
        };


        public String getChannelId() {
            return channelId;
        }

        public void setChannelId(String channelId) {
            this.channelId = channelId;
            this.channelName = BiPlatformManager.getChannelNameById(channelId);
        }

        public String getChannelName() {
            return channelName;
        }

        public void setChannelName(String channelName) {
            this.channelName = channelName;
        }

        public String getDay() {
            return day;
        }

        public void setDay(String day) {
            this.day = day;
        }

        public int getNewUser() {
            return newUser;
        }

        public void setNewUser(int newUser) {
            this.newUser = newUser;
        }
    }
}
